﻿Imports System

Imports Microsoft.VisualStudio.TestTools.UnitTesting

Imports paycircuit.com.google.iap


'''<summary>
'''This is a test class for JWTHelpersTest and is intended
'''to contain all JWTHelpersTest Unit Tests
'''</summary>
<TestClass()> _
Public Class JWTHelpersTest

    '*** I M P O R T A N T ***
    'use your credentials
    Const MY_SELLER_ID As String = "YOUR_SELLER_ID"
    Const MY_SELLER_SECRET As String = "YOUR_SELLER_SECRET"

    Const MY_PRODUCTION_SELLER_ID As String = "YOUR_PRODUCTION_SELLER_ID"
    Const MY_PRODUCTION_SELLER_SECRET As String = "YOUR_PRODUCTION_SELLER_SECRET"

    Const MY_POSTBACK_TYP As String = "google/payments/inapp/item/v1/postback/buy"
    Const THE_ISSUER As String = "Google"
    '*** I M P O R T A N T ***



    Private testContextInstance As TestContext

    '''<summary>
    '''Gets or sets the test context which provides
    '''information about and functionality for the current test run.
    '''</summary>
    Public Property TestContext() As TestContext
        Get
            Return testContextInstance
        End Get
        Set(value As TestContext)
            testContextInstance = value
        End Set
    End Property

#Region "Additional test attributes"
    '
    'You can use the following additional attributes as you write your tests:
    '
    'Use ClassInitialize to run code before running the first test in the class
    '<ClassInitialize()>  _
    'Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
    'End Sub
    '
    'Use ClassCleanup to run code after all tests in a class have run
    '<ClassCleanup()>  _
    'Public Shared Sub MyClassCleanup()
    'End Sub
    '
    'Use TestInitialize to run code before running each test
    '<TestInitialize()>  _
    'Public Sub MyTestInitialize()
    'End Sub
    '
    'Use TestCleanup to run code after each test has run
    '<TestCleanup()>  _
    'Public Sub MyTestCleanup()
    'End Sub
    '
#End Region


    '''<summary>
    '''A test for buildJWT. Currently will display "expected exception" assertion because of exp value. (exp: 1308873464, iat:1308874464)
    ''' Modify the exp value to be > than iat and set your own seller ID and seller secret to run this test.
    '''</summary>
    <TestMethod()> _
    Public Sub buildJWTTest()
        Dim header As JWTHeaderObject = New JWTHeaderObject(JWTHeaderObject.JWTHash.HS256, "1")
        Dim payload As InAppItemObject = New InAppItemObject() With {.exp = 1308873464, .request = New InAppItemRequestObject() With {.name = "Gold Star", .description = "A shining badge of distinction",
                                                                     .price = "3.99", .currencyCode = "USD", .sellerData = "some opaque data"}, .iss = MY_SELLER_ID, .iat = 1308874464}

        Dim key As String = MY_SELLER_SECRET
        Dim expected As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ.eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Imdvb2cucGF5bWVudHMuaW5hcHAuYnV5SXRlbSIsImlhdCI6MTMwODg3NTI4NCwiZXhwIjoxMzA4OTYxNjg0LCJpc29DdXJyZW5jeUNvZGUiOiJVU0QiLCJpdGVtUHJpY2UiOjMuOTksInNlbGxlckRhdGEiOiJzb21lIG9wYXF1ZSBkYXRhIiwiaXRlbU5hbWUiOiJHb2xkIFN0YXIiLCJpdGVtRGVzY3JpcHRpb24iOiJBIHNoaW5pbmcgYmFkZ2Ugb2YgZGlzdGluY3Rpb24ifQ.axE0AjD8ygX-jljhEWwQb5arOaEBGcNB7U-GFKzCGTA"
        Dim actual As String
        Try
            actual = JWTHelpers.buildJWT(header, payload, key)
            If MY_SELLER_ID = "YOUR SELLER ID" Or MY_SELLER_SECRET = "YOUR SELLER SECRET" Then
                Assert.Inconclusive("You must use your own seller id and seller secret to run this test")
            Else
                Assert.AreEqual(expected, actual)
            End If
        Catch ex As Exception
            Assert.Inconclusive(String.Format("Expected exception: invalid exp value. Error message: {0}", ex.Message))
        End Try
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    <TestMethod()>
    Public Sub buildJWT1()


        Dim HeaderObj As New JWTHeaderObject(JWTHeaderObject.JWTHash.HS256, "1", "JWT")
        Dim request As New InAppItemRequestObject() With
            {
                .name = "Burp",
                .description = "A digital representation of food for your palete",
                .price = "0.99",
                .currencyCode = RequestObject.SupportedCurrencies.USD.ToString()
            }
        Dim ClaimObj As New InAppItemObject(request) With {.iss = MY_SELLER_ID, .exp = .iat + 3600}


        Dim key As String = MY_SELLER_SECRET

        Dim jwt As String = JWTHelpers.buildJWT(HeaderObj, ClaimObj, MY_SELLER_SECRET)

        Assert.IsFalse(String.IsNullOrEmpty(jwt), String.Format("Generated JWT: {0}:", jwt))
        Assert.Inconclusive(jwt)

    End Sub


    '''<summary>
    '''A test for buildJWT
    '''</summary>
    <TestMethod()> _
    Public Sub buildBADJWTTest()
        Dim header As JWTHeaderObject = New JWTHeaderObject(JWTHeaderObject.JWTHash.none, "kid")
        Dim payload As InAppItemObject = New InAppItemObject() With {.iat = 1308875284, .exp = 1308875464, .request = New InAppItemRequestObject() With {.name = "Gold Star", .description = "A shining badge of distinction",
                                                                     .price = "3.99", .currencyCode = "USD", .sellerData = "some opaque data"}, .iss = MY_SELLER_ID}
        Dim key As String = MY_SELLER_SECRET
        Dim actual As String
        actual = JWTHelpers.buildJWT(header, payload, key)
        Assert.Inconclusive(String.Format("Unsupported JWT (no signatur): {0}", actual))
    End Sub

    ''' <summary>
    ''' Serializaion test. A bad exp value will prevent serialization to JSON
    ''' </summary>
    ''' <remarks></remarks>
    <TestMethod()>
    Public Sub buildBadJWTClaim()
        Dim badExp = JWTHelpers.myServerClock - 40
        'Note: the default iat is offset by 1 minute
        Dim claim As New InAppItemObject With {.exp = badExp, .iss = "required", .request = New InAppItemRequestObject() With {.name = "foo"}}
        Dim actual As String = JSONHelpers.dataContractToJSON(claim)
        Assert.IsTrue(Not String.IsNullOrEmpty(actual), String.Format("Expected Failure: exp value {0} failure. Must be > iat {1} and < 1 hour. Difference {2} seconds", claim.exp, claim.iat, claim.exp - claim.iat))
        Assert.Inconclusive(String.Format("Expected behavior. Good exp: {0} iat {1}. exp is {2} seconds from iat", claim.exp, claim.iat, claim.exp - claim.iat))
    End Sub


    '''<summary>
    '''A test for dataContractJSONToObj
    '''</summary>
    <TestMethod()> _
    Public Sub dataContractJSONToObjTest()
        'TODO: base64url strings are sample JWT header and/or Payload - use Google's demo/test page to obtain your own
        Dim jwtheader As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ"
        Dim jwtpayload As String = "eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Imdvb2cucGF5bWVudHMuaW5hcHAuYnV5SXRlbSIsImlhdCI6MTMwODg3MjE3MiwiZXhwIjoxMzA4OTU4NTcyLCJpc29DdXJyZW5jeUNvZGUiOiJVU0QiLCJpdGVtUHJpY2UiOjMuMCwic2VsbGVyRGF0YSI6InNvbWUgb3BhcXVlIGRhdGEiLCJpdGVtTmFtZSI6IkdvbGQgU3RhciIsIml0ZW1EZXNjcmlwdGlvbiI6IkEgc2hpbmluZyBiYWRnZSBvZiBkaXN0aW5jdGlvbiJ9"
        Dim o As Object = JSONHelpers.dataContractJSONToObj(jwtheader, New JWTHeaderObject())
        Dim o2 As Object = JSONHelpers.dataContractJSONToObj(jwtpayload, New InAppItemObject())
        Assert.IsInstanceOfType(o, New JWTHeaderObject().GetType)
        Assert.IsInstanceOfType(o2, New InAppItemObject().GetType, "Expected behavior: INVALID exp")
    End Sub

    '''<summary>
    '''A test for dataContractToJSON
    '''</summary>
    <TestMethod()> _
    Public Sub dataContractToJSONTest()
        'TODO: base64url strings are sample JWT header and/or Payload - use Google's demo/test page to obtain your own
        Dim jwtheader As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ"
        Dim o As Object = JSONHelpers.dataContractJSONToObj(jwtheader, New JWTHeaderObject())
        Dim expected As String = "{""alg"":""HS256"",""kid"":""1""}"
        Dim actual As String
        actual = JSONHelpers.dataContractToJSON(o)
        Assert.AreEqual(expected, actual)
    End Sub

    '''<summary>
    '''A test for jwtDecodeB64
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")> _
    Public Sub jwtDecodeB64Test()
        'TODO: base64url strings are sample JWT header and/or Payload - use Google's demo/test page to obtain your own
        Dim s As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ"
        Dim expected As String = "{""alg"":""HS256"",""kid"":""1""}"
        Dim actual As String
        actual = JWTHelpers_Accessor.jwtDecodeB64Url(s)
        Assert.AreEqual(expected, actual)
    End Sub

    '''<summary>
    '''A test for jwtEncodeB64
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")> _
    Public Sub jwtEncodeB64Test()
        'TODO: base64url strings are sample JWT header and/or Payload - use Google's demo/test page to obtain your own
        Dim s As String = "{""alg"":""HS256"",""kid"":""1""}"
        Dim expected As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ"
        Dim actual As String
        actual = JWTHelpers_Accessor.jwtEncodeB64Url(s)
        Assert.AreEqual(expected, actual)
    End Sub

    '''<summary>
    '''A test for jwtHMAC256
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")> _
    Public Sub jwtHMAC256Test()
        'TODO: base64url strings are sample JWT header and/or Payload - use Google's demo/test page to obtain your own
        Dim JWSSigningInput As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ.eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Imdvb2cucGF5bWVudHMuaW5hcHAuYnV5SXRlbSIsImlhdCI6MTMwODg3MjE3MiwiZXhwIjoxMzA4OTU4NTcyLCJpc29DdXJyZW5jeUNvZGUiOiJVU0QiLCJpdGVtUHJpY2UiOjMuMCwic2VsbGVyRGF0YSI6InNvbWUgb3BhcXVlIGRhdGEiLCJpdGVtTmFtZSI6IkdvbGQgU3RhciIsIml0ZW1EZXNjcmlwdGlvbiI6IkEgc2hpbmluZyBiYWRnZSBvZiBkaXN0aW5jdGlvbiJ9"
        Dim hkey As String = MY_SELLER_SECRET

        'Exception
        'hkey = String.Empty
        'JWSSigningInput = String.Empty

        Dim expected As String = "ckzgZPl-7PuN1tttjGy-eFiXKzGC8iEp46bMCtBTrCY"
        Dim actual As String = String.Empty

        Try
            actual = JWTHelpers_Accessor.jwtHMAC256(JWSSigningInput, hkey)
        Catch ex As Exception
            Throw New AssertFailedException(If(ex.InnerException IsNot Nothing, ex.InnerException.ToString, ex.Message))
        End Try

        Assert.AreEqual(expected, actual, "Use your credentials to use this test")
    End Sub

    '''<summary>
    '''A test for jwtHMAC384 - IGNORED
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")>
     <Ignore()> _
    Public Sub jwtHMAC384Test()
        Dim JWSSigningInput As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim hkey As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim expected As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim actual As String
        actual = JWTHelpers_Accessor.jwtHMAC384(JWSSigningInput, hkey)
        Assert.AreEqual(expected, actual)
        Assert.Inconclusive("Verify the correctness of this test method.")
    End Sub

    '''<summary>
    '''A test for jwtHMAC512 - IGNORED 
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")>
     <Ignore()> _
    Public Sub jwtHMAC512Test()
        Dim JWSSigningInput As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim hkey As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim expected As String = String.Empty ' TODO: Initialize to an appropriate value
        Dim actual As String
        actual = JWTHelpers_Accessor.jwtHMAC512(JWSSigningInput, hkey)
        Assert.AreEqual(expected, actual)
        Assert.Inconclusive("Verify the correctness of this test method.")
    End Sub

    '''<summary>
    '''A test for parseJWTHashEnum
    '''</summary>
    <TestMethod()> _
    Public Sub parseJWTHashEnumTest()
        Dim s As String = "HS256" 'HS512 HS384
        Dim expected As JWTHeaderObject.JWTHash = JWTHeaderObject.JWTHash.HS256
        Dim actual As JWTHeaderObject.JWTHash
        actual = JWTHelpers.parseJWTHashEnum(s)
        Assert.AreEqual(expected, actual)
    End Sub

    '''<summary>
    '''A test for verifyJWT. Use this test to match this Google demo page values (not for POSTBACK verification)
    '''</summary>
    ''' <remarks>NOTE: In Goolge's demo, epxiration (exp) value is currently 1 day from iat, this wil fail verification in this libary. Limit is 1 hour from iat. Adjust the exp value in the Google Demo and provide a value that is less than 60 minutes from iat, update the JSON and use in this test. </remarks>
    <TestMethod()> _
    Public Sub verifyJWTTest()
        '************************* !!!!!!!!!! *************************
        ' SEE REMARKS
        '************************* !!!!!!!!!! *************************

        'JWT Header part: SAMPLE VALUE IS FROM GOOGLE DEMO PAGE (replace with data from your account test page)
        Dim jwthExpected As String = "eyJhbGciOiJIUzI1NiJ9"

        'JWT Payload part: SAMPLE VALUE IS FROM GOOGLE DEMO PAGE (replace with data from your account test page)
        '   This is the string in 2nd segment of the JWT - [segment1_header].[segment2_payload].[segment3_signature]
        Dim jwtpExpected As String = "eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiaWF0IjoxMzgxNjkzMDY4LCJleHAiOjEzODE2OTM4MTMsInJlcXVlc3QiOnsiY3VycmVuY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIzLjAwIiwibmFtZSI6IkdvbGQgU3RhciIsInNlbGxlckRhdGEiOiJzb21lIG9wYXF1ZSBkYXRhIiwiZGVzY3JpcHRpb24iOiJBIHNoaW5pbmcgYmFkZ2Ugb2YgZGlzdGluY3Rpb24ifX0"

        'To test:
        'provide the jwt you receive in the callback or use Google demo: https://sandbox.google.com/checkout/customer/gadget/inapp/demo.html
        'This is the entire JWT string in the Google Demo
        Dim jwtString As String = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9pdGVtL3YxIiwiaWF0IjoxMzgxNjkzMDY4LCJleHAiOjEzODE2OTM4MTMsInJlcXVlc3QiOnsiY3VycmVuY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIzLjAwIiwibmFtZSI6IkdvbGQgU3RhciIsInNlbGxlckRhdGEiOiJzb21lIG9wYXF1ZSBkYXRhIiwiZGVzY3JpcHRpb24iOiJBIHNoaW5pbmcgYmFkZ2Ugb2YgZGlzdGluY3Rpb24ifX0.w8IQzr3nTuEI9ISnRfKihGvGZIOevUdP9SWPuKmhYoI"

        'Your Seller Secret here
        Dim key As String = MY_SELLER_SECRET

        Dim expected As Boolean = True
        Dim actual As Boolean

        Dim jwth As String = String.Empty
        Dim jwtp As String = String.Empty
        actual = JWTHelpers.verifyJWT(jwtString, key, jwth, jwtp)


        Dim HeaderObj As JWTHeaderObject = Nothing
        Dim ClaimObj As InAppItemObject = Nothing

        Assert.AreEqual(jwthExpected, jwth, False)
        Assert.AreEqual(jwtpExpected, jwtp, False)
        Assert.AreEqual(expected, actual, "You must replace the *sample data* with information from your own Google test/demo page")

    End Sub


    '''<summary>
    '''A test for verifyJWT - single, subscription and failure
    '''</summary>
    <TestMethod()> _
    Public Sub verifyJWTTest2()

        Dim JWTHeader As JWTHeaderObject = Nothing
        Dim JWTPayload As InAppItemObject = Nothing

        Dim iss As String = THE_ISSUER

        'Generate bad/good payloads
        '*~*~*~*~*~*~*~*~*~*~*~
        Dim testhdr As String = "{""alg"":""\u0048S256"",""kid"":""1""}"
        Dim b64urlheader As String = JWTHelpers_Accessor.jwtEncodeB64Url(testhdr)

        'Dim badjwtpayload As String = "{""iss"":""GOOgle"",""iat"":1308875284,""aud"":""goog.payments.inapp.buyItem"", ""isoCurrencyCode"":""USD"",  ""itemPrice"":3.0,  ""sellerData"":""some opaque data"",  ""itemName"":""Gold Star"",  ""itemDescription"":""A shining badge of distinction""}"

        Dim _iat = JWTHelpers.myServerClock()
        'exp must be greater than current UTC time
        Dim _exp As String = CInt((DateTime.UtcNow.AddMinutes(10).Ticks - 621355968000000000) / 10000000).ToString

        'Good
        Dim goodjwtpayload As String = "{""iss"":""Google"",""aud"":""" & MY_SELLER_ID & """,""typ"":""google/payments/inapp/item/v1/postback/buy"",""iat"":" & _iat & ",""exp"":" & _exp & ",""request"":{""currencyCode"":""USD"",""price"":""31.95"",""name"":""Some Virtual Widget + $9 Donation"",""sellerData"":"""",""description"":""Sumatra, Garuda, Jetta""},""response"":{""orderId"":""1234567890.C.111213141516""}}"

        ''Subscription Postback
        'Dim goodjwtpayload As String = "{""iss"":""Google"",""aud"":""" & MY_SELLER_ID & """,""typ"":""google/payments/inapp/item/v1/postback/buy"",""iat"":" & _iat & ",""exp"":" & _exp & ",""request"":{""name"":""Some Virtual Widget + $9 Donation"",""sellerData"":"""",""description"":""Sumatra, Garuda, Jetta"",""initialPayment"":{""currencyCode"":""USD"",""price"":""31.95"",""paymentType"":""prorated""},""recurrence"":{""frequency"":""monthly""}},""response"":{""orderId"":""1234567890.C.111213141516""}}"

        ''Failure Postback
        'Dim goodjwtpayload As String = "{""iss"":""Google"",""aud"":""" & MY_SELLER_ID & """,""typ"":""google/payments/inapp/subscription/v1/canceled"",""iat"":" & _iat & ",""exp"":" & _exp & ",""response"":{""orderId"":""1234567890.C.111213141516"",""statusCode"":""SUBSCRIPTION_CANCELED""}}"


        'Empty orderID will fail verifyJWT
        'Dim goodjwtpayload As String = "{""iss"":""Google"",""aud"":""" & MY_SELLER_ID & """,""typ"":""goog.payments.inapp.buyItem.v1.postback"",""iat"":" & _iat & ",""exp"":" & _exp & ",""request"":{""currencyCode"":""USD"",""price"":""31.95"",""name"":""Some Virtual Widget + $9 Donation"",""sellerData"":"""",""description"":""Sumatra, Garuda, Jetta""},""response"":{""orderId"":""""}}"

        'No response will fail verifyJWT
        'Dim goodjwtpayload As String = "{""iss"":""Google"",""aud"":""" & MY_SELLER_ID & """,""typ"":""goog.payments.inapp.buyItem.v1.postback"",""iat"":" & _iat & ",""exp"":" & _exp & ",""request"":{""currencyCode"":""USD"",""price"":""31.95"",""name"":""Some Virtual Widget + $9 Donation"",""sellerData"":"""",""description"":""Sumatra, Garuda, Jetta""}}"

        Dim encoded As String = JWTHelpers_Accessor.jwtEncodeB64Url(goodjwtpayload)
        Dim sig As String = JWTHelpers_Accessor.jwtHMAC256(String.Concat(b64urlheader, ".", encoded), MY_SELLER_SECRET)
        Dim testJWT As String = String.Concat(b64urlheader, ".", encoded, ".", sig)

        Dim key As String = MY_SELLER_SECRET
        Dim expected As Boolean = True
        Dim actual As Boolean
        actual = JWTHelpers.verifyJWT(iss, MY_SELLER_ID, MY_POSTBACK_TYP, 1, testJWT, key, JWTHeader, JWTPayload)

        Assert.IsTrue(JWTHeader IsNot Nothing, "Invalid header")
        Assert.IsTrue(JWTPayload IsNot Nothing, "Failed JWT signature test or Invalid payload")
        Assert.AreEqual(expected, actual, "Expected Failed strict JWT verification")
    End Sub


    ''' <summary>
    ''' Gernerate failure test
    ''' </summary>
    ''' <remarks></remarks>
    <TestMethod()> _
    Public Sub verifyJWTTest3()

        Dim JWTHeader As JWTHeaderObject = Nothing
        Dim JWTPayload As InAppItemObject = Nothing

        Dim iss As String = THE_ISSUER

        'Generate bad/good payloads
        '*~*~*~*~*~*~*~*~*~*~*~
        'no alg value (none)
        'Dim header_gen As JWTHeaderObject = New JWTHeaderObject()

        'Dim testhdr As String = JSONHelpers.dataContractToJSON(header_gen)
        Dim testhdr As String = "{""foo"":""foo"",""bar"":""none""}"

        Dim b64urlheader As String = JWTHelpers_Accessor.jwtEncodeB64Url(testhdr)

        Dim _iat = JWTHelpers.myServerClock()
        'exp must be greater than current UTC time
        Dim _exp As String = CInt((DateTime.UtcNow.AddMinutes(1).Ticks - 621355968000000000) / 10000000).ToString

        'Payload from Google
        Dim goodjwtpayload As String = "{""iss"":""Google"",""iat"":" & _iat & ",""exp"":" & _exp & ",""aud"":""" & MY_SELLER_ID & """, ""isoCurrencyCode"":""USD"",  ""itemPrice"":3.0,  ""sellerData"":""some opaque data"",  ""itemName"":""Gold Star"",  ""itemDescription"":""A shining badge of distinction""}"

        'use good or bad payload
        Dim encoded As String = JWTHelpers_Accessor.jwtEncodeB64Url(goodjwtpayload)

        Dim sig As String = JWTHelpers_Accessor.jwtHMAC256(String.Concat(b64urlheader, ".", encoded), MY_SELLER_SECRET)
        Dim testJWT As String = String.Concat(b64urlheader, ".", encoded, ".", sig)


        Dim key As String = MY_SELLER_SECRET
        Dim expected As Boolean = True
        Dim actual As Boolean
        actual = JWTHelpers.verifyJWT(iss, MY_SELLER_ID, MY_POSTBACK_TYP, 0, testJWT, key, JWTHeader, JWTPayload)

        Assert.IsTrue(JWTHeader IsNot Nothing, String.Format("Expected result: Invalid header - {0}", JWTHelpers_Accessor.jwtDecodeB64Url(b64urlheader)))
        Assert.IsTrue(JWTPayload IsNot Nothing, "Failed JWT signature test or Invalid payload")
        Assert.AreEqual(expected, actual, "Failed strict JWT verification")
    End Sub


    '''<summary>
    '''A test for verifySignature
    ''' http://self-issued.info/docs/draft-jones-json-web-signature.html
    ''' 9.1.  Unicode Comparison Security Issues
    '''</summary>
    <TestMethod(), _
     DeploymentItem("paycircuit.com.google.iap.lib.dll")> _
    Public Sub verifySignatureTest()
        'Generate bad/good payloads
        '*~*~*~*~*~*~*~*~*~*~*~
        Dim iss As String = THE_ISSUER

        Dim testhdr As String = "{""alg"":""\u0048\u0053256"",""kid"":""\u0073ig""}"
        Dim _exp As String = CInt((DateTime.UtcNow.AddMinutes(1).Ticks - 621355968000000000) / 10000000).ToString
        Dim goodjwtpayload As String = "{""iss"":""Google"",""iat"":1308875284,""exp"":" & _exp & ",""aud"":""" & MY_SELLER_ID & """, ""isoCurrencyCode"":""USD"",  ""itemPrice"":3.0,  ""sellerData"":""some opaque data"",  ""itemName"":""Gold Star"",  ""itemDescription"":""A shining badge of distinction""}"

        Dim jwth As String = JWTHelpers_Accessor.jwtEncodeB64Url(testhdr)
        Dim jwtp As String = JWTHelpers_Accessor.jwtEncodeB64Url(goodjwtpayload)
        Dim sig As String = JWTHelpers_Accessor.jwtHMAC256(String.Concat(jwth, ".", jwtp), MY_SELLER_SECRET)

        Dim header As JWTHeaderObject = TryCast(dataContractJSONToObj(jwth, New JWTHeaderObject()), JWTHeaderObject)
        Dim alg As String = If(header IsNot Nothing, header.alg, String.Empty)

        Dim key As String = MY_SELLER_SECRET

        Dim expected As Boolean = True
        Dim actual As Boolean
        actual = JWTHelpers_Accessor.verifySignature(alg, jwth, jwtp, sig, key)
        Assert.AreEqual(expected, actual)
    End Sub


    <TestMethod()> _
    Public Sub debugInAppPaymentsDevGroup()


        'Dim testhdr As String = JSONHelpers.dataContractToJSON(header_gen)
        Dim _testhdr As String = "{""alg"": ""HS256"", ""typ"": ""JWT""}"

        Dim _b64urlheader As String = JWTHelpers_Accessor.jwtEncodeB64Url(_testhdr)

        'Dim _iat = JWTHelpers.myServerClock()
        Dim _iat = CInt((DateTime.UtcNow.AddMinutes(-4).Ticks - 621355968000000000) / 10000000).ToString
        'exp must be greater than current UTC time
        Dim _exp As String = CInt((DateTime.UtcNow.AddMinutes(-2).Ticks - 621355968000000000) / 10000000).ToString

        Dim _payloadStr As String = "{""aud"": ""Google"", ""iss"": " & MY_SELLER_ID & ",""request"": {""currencyCode"": ""USD"", ""price"": ""10.50"", ""sellerData"": ""userID:1224245,offerCODE:3098576987,affiliate:aksdfbovu9j"", ""name"": ""Piece of Cake"", ""description"": ""Virtual chocolate cake to fill your virtual tummy""}, ""exp"": " & _exp & ", ""iat"": " & _iat & ", ""typ"": ""google/payments/inapp/item/v1""}"

        'use good or bad payload
        Dim _encodedPayload As String = JWTHelpers_Accessor.jwtEncodeB64Url(_payloadStr)

        Dim _sig As String = JWTHelpers_Accessor.jwtHMAC256(String.Concat(_b64urlheader, ".", _encodedPayload), MY_SELLER_SECRET)

        Dim _testJWT As String = String.Concat(_b64urlheader, ".", _encodedPayload, ".", _sig)

        Assert.Inconclusive(_testJWT)


    End Sub


    '''<summary>
    '''A test for dateToEpochTime
    '''</summary>
    <TestMethod()> _
    Public Sub dateToEpochTimeTest()
        Dim t As DateTime = New DateTime(Year:=2012, Month:=10, Day:=14, Hour:=23, Minute:=0, Second:=0, millisecond:=0)
        Dim expected As Integer = 1350280800
        Dim actual As Integer
        actual = JWTHelpers.dateToEpochTime(t)
        Assert.AreEqual(expected, actual)
    End Sub

    '''<summary>
    '''A test for buildJWT - Subscriptions
    '''</summary>
    <TestMethod()> _
    Public Sub buildJWTTest_Subscriptions()
        Dim HeaderObj As New JWTHeaderObject(JWTHeaderObject.JWTHash.HS256, "1")

        Dim request As New InAppItemSubscriptionRequestObject() With {.name = "Weekly Cake", .description = "Virtual chocolate cake to fill your virtual tummy every week",
                                                                      .initialPayment = New InAppSubscriptionInitialPaymentObject() With
                                                                                        {
                                                                                            .price = "10.50", .currencyCode = RequestObject.SupportedCurrencies.USD.ToString(), .paymentType = "prorated"
                                                                                                                                 },
                                                                      .recurrence = New InAppSubscriptionRecurrenceObject() With
                                                                                    {
                                                                                        .recurrenceStartDate = New DateTime(2013, 11, 15),
                                                                                        .frequency = "monthly",
                                                                                        .price = "4.99",
                                                                                        .currencyCode = "USD"
                                                                                    }
                                                                     }



        Dim ClaimObj As New InAppItemObject(request) With {.iss = MY_SELLER_ID}
        ClaimObj.exp = ClaimObj.iat + 3600
        Dim sellerSecret As String = MY_SELLER_SECRET
        Dim actual As String = JWTHelpers.buildJWT(HeaderObj, ClaimObj, sellerSecret)
        Assert.Inconclusive("the JWT string: " & actual)
    End Sub



    <TestMethod()> _
    Public Sub verifySubscriptionJWTTest()

        'JWT Header part: SAMPLE VALUE IS FROM GOOGLE DEMO PAGE (replace with data from your account test page)
        Dim jwthExpected As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ" ' {"alg":"HS256","kid":"1"}

        'JWT Payload part: SAMPLE VALUE IS FROM GOOGLE DEMO PAGE (replace with data from your account test page)
        '   This is the string in 2nd segment of the JWT - [segment1_header].[segment2_payload].[segment3_signature]
        Dim jwtpExpected As String = "eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZVwvcGF5bWVudHNcL2luYXBwXC9pdGVtXC92MSIsImlhdCI6MTM4MTc2MzQ1MSwiZXhwIjoxMzgxNzY3MDUxLCJyZXF1ZXN0Ijp7ImRlc2NyaXB0aW9uIjoiVmlydHVhbCBjaG9jb2xhdGUgY2FrZSB0byBmaWxsIHlvdXIgdmlydHVhbCB0dW1teSBldmVyeSB3ZWVrIiwiaW5pdGlhbFBheW1lbnQiOnsiY3VycmVuY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIxMC41MCIsInBheW1lbnRUeXBlIjoicHJvcmF0ZWQifSwibmFtZSI6IldlZWtseSBDYWtlIiwicmVjdXJyZW5jZSI6eyJjdXJyZW5jeUNvZGUiOiJVU0QiLCJwcmljZSI6IjQuOTkiLCJmcmVxdWVuY3kiOiJtb250aGx5Iiwic3RhcnRUaW1lIjoxMzg0NTAyNDAwfX19"

        'To test:
        'provide the jwt you receive in the callback or use Google demo: https://sandbox.google.com/checkout/customer/gadget/inapp/demo.html
        'This is the entire JWT string in the Google Demo
        Dim jwtString As String = "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ.eyJpc3MiOiIxMjE3ODk0NTA3MTU0MTc1MDY3MCIsImF1ZCI6Ikdvb2dsZSIsInR5cCI6Imdvb2dsZVwvcGF5bWVudHNcL2luYXBwXC9pdGVtXC92MSIsImlhdCI6MTM4MTc2MzQ1MSwiZXhwIjoxMzgxNzY3MDUxLCJyZXF1ZXN0Ijp7ImRlc2NyaXB0aW9uIjoiVmlydHVhbCBjaG9jb2xhdGUgY2FrZSB0byBmaWxsIHlvdXIgdmlydHVhbCB0dW1teSBldmVyeSB3ZWVrIiwiaW5pdGlhbFBheW1lbnQiOnsiY3VycmVuY3lDb2RlIjoiVVNEIiwicHJpY2UiOiIxMC41MCIsInBheW1lbnRUeXBlIjoicHJvcmF0ZWQifSwibmFtZSI6IldlZWtseSBDYWtlIiwicmVjdXJyZW5jZSI6eyJjdXJyZW5jeUNvZGUiOiJVU0QiLCJwcmljZSI6IjQuOTkiLCJmcmVxdWVuY3kiOiJtb250aGx5Iiwic3RhcnRUaW1lIjoxMzg0NTAyNDAwfX19.94UjNxNA15VgkpDphGKgdkC1k4xGHLl7k0OT2lFoAJg"

        Dim key As String = MY_SELLER_SECRET

        Dim expected As Boolean = True
        Dim actual As Boolean

        Dim jwth As String = String.Empty
        Dim jwtp As String = String.Empty
        actual = JWTHelpers.verifyJWT(jwtString, key, jwth, jwtp)


        Dim HeaderObj As JWTHeaderObject = Nothing
        Dim ClaimObj As InAppItemObject = Nothing

        Assert.AreEqual(jwthExpected, jwth, False)
        Assert.AreEqual(jwtpExpected, jwtp, False)
        Assert.AreEqual(expected, actual, "You must replace the *sample data* with information from your own Google test/demo page")

    End Sub

    ''' <summary>
    ''' To use this test, obtain the postback JWT from Google - you will need to go through an actual purchase to get the postback JWT
    ''' </summary>
    ''' <remarks></remarks>
    <TestMethod()> _
    Public Sub verifyGooglePostBackTest()

        Dim JWTHeader As JWTHeaderObject = Nothing
        Dim JWTPayload As InAppItemObject = Nothing

        Dim iss As String = THE_ISSUER

        'Successful Subscription postback
        Dim testSubscriptionPostBack As String = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJHb29nbGUiLCJyZXF1ZXN0Ijp7ImRlc2NyaXB0aW9uIjoiQSBkaWdpdGFsIHJlcHJlc2VudGF0aW9uIG9mIGZvb2QgZm9yIHlvdXIgcGFsZXRlIGRlbGl2ZXJlZCBldmVyeSBtb250aCEiLCJpbml0aWFsUGF5bWVudCI6eyJjdXJyZW5jeUNvZGUiOiJVU0QiLCJwcmljZSI6IjEuOTkiLCJwYXltZW50VHlwZSI6InByb3JhdGVkIn0sIm5hbWUiOiJNb250aGx5IEJ1cnAiLCJyZWN1cnJlbmNlIjp7ImN1cnJlbmN5Q29kZSI6IlVTRCIsInByaWNlIjoiMC45OSIsImZyZXF1ZW5jeSI6Im1vbnRobHkiLCJudW1SZWN1cnJlbmNlcyI6IjEyIiwic3RhcnRUaW1lIjoxMzg0NzIxMzI3fX0sInJlc3BvbnNlIjp7Im9yZGVySWQiOiJHV0RHX1MuOTJkMGM1NTUtYmM4Mi00MDVhLWI1NzEtN2JhMWE3MTE2NmEwIn0sInR5cCI6Imdvb2dsZS9wYXltZW50cy9pbmFwcC9zdWJzY3JpcHRpb24vdjEvcG9zdGJhY2svYnV5IiwiYXVkIjoiMTIxNzg5NDUwNzE1NDE3NTA2NzAiLCJpYXQiOjEzODIwMzkzNDUsImV4cCI6MTM4MjAzOTM2NX0.T_RoiBwgqX5ao0nWSr2h-s2ZWeyEgD88aZK4gBMYAcY"

        'failure postback
        Dim testJWT As String = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJHb29nbGUiLCJyZXNwb25zZSI6eyJvcmRlcklkIjoiR1dER19TLjFmNThjODg0LTc2MmEtNDkwOC1hMGYyLTc4Y2E4OWI5Zjk4NCIsInN0YXR1c0NvZGUiOiJTVUJTQ1JJUFRJT05fQ0FOQ0VMRUQifSwidHlwIjoiZ29vZ2xlL3BheW1lbnRzL2luYXBwL3N1YnNjcmlwdGlvbi92MS9jYW5jZWxlZCIsImF1ZCI6IjEyMTc4OTQ1MDcxNTQxNzUwNjcwIiwiaWF0IjoxMzgyMDU1MTExLCJleHAiOjEzODIwNTUxMzF9.QmGxWVP2J7lx2naETYFwLKzajoPGw5cbkUXfn29MELw"

        Dim key As String = MY_SELLER_SECRET
        Dim expected As Boolean = True
        Dim actual As Boolean
        actual = JWTHelpers.verifyJWT(iss, MY_SELLER_ID, MY_POSTBACK_TYP, 1440, testSubscriptionPostBack, key, JWTHeader, JWTPayload) 'note clock adjustment...only for debugging!!!

        Assert.IsTrue(JWTHeader IsNot Nothing, "Invalid header")
        Assert.IsTrue(JWTPayload IsNot Nothing, "Failed JWT signature test or Invalid payload")
        Assert.AreEqual(expected, actual, "Expected Failed strict JWT verification")

        Assert.Inconclusive(ParsePostBackData(JWTPayload, JWTHeader))
    End Sub


    Private Function ParsePostBackData(ByVal ClaimObj As InAppItemObject, ByVal HeaderObj As JWTHeaderObject) As String
        Dim foo As String = String.Format("JWT Headers{0}JWT Algo: {1}{0}JWT kid: {2}{0}JWT typ: {3}{0}{0}", Environment.NewLine, HeaderObj.alg, HeaderObj.kid, HeaderObj.typ)
        Dim bar As String = String.Format("JWT Payload{0}JWT aud: {1}{0}JWT iss: {2}{0}JWT orderid: {3}{0}JWT sellerdata: {4}{0}JWT iat: {5}{0}JWT itemName: {6}{0}JWT itemPrice: {7:c}{0}JWT Item Description: {8}{0}JWT exp: {9}{0}JWT typ: {10}{0}{0}",
                                          Environment.NewLine,
                                          ClaimObj.aud,
                                          ClaimObj.iss,
                                          ClaimObj.response.orderId,
                                          If(ClaimObj.isSuccessPostback, ClaimObj.request.sellerData, "Failure Postback does not have request.sellerData"),
                                          ClaimObj.iat,
                                          If(ClaimObj.isSuccessPostback, ClaimObj.request.name, "Failure Postback does not have request.name"),
                                          If(ClaimObj.isSuccessPostback AndAlso ClaimObj.isSingleItem, ClaimObj.request.price,
                                             If(ClaimObj.isSuccessPostback AndAlso ClaimObj.isSubscriptionItem, ClaimObj.request.initialPayment.price, "Failure Postback does not have request.price")),
                                           If(ClaimObj.isSuccessPostback, ClaimObj.request.description, "Failure Postback does not have request.description"),
                                          ClaimObj.exp,
                                          ClaimObj.typ
                                          )
        If ClaimObj.isFailurePostback Then
            bar = bar & String.Format("Failure Status Code: {0}", ClaimObj.response.statusCode)
        End If

        Return foo & Environment.NewLine & bar

    End Function
End Class
